//我觉得吧，我写这些代码我肯定是不可能一次性把所有的给写完，但是我可以做一个平替，就是遮住部分代码替换成自己的
//先是宏观的，每份文件的目的是做什么
//再是微观的，这份代码具体的接口，内部的细节
//比如TcpServer的功能就是负责服务器和客户端的连接，IO信息交互(IO信息交互的实现主要是http服务，http服务的制定在更上层)
//具体的功能涉及到Socket的功能，服务器启动进行while循环进行服务器和客户端的连接以及IO交互
//怎么替换呢，就是由上到下找，看哪个利用了当前文件，直接换成Test...来测试


#pragma once

#include <iostream>
#include <memory>
#include <functional>
#include <sys/wait.h>
#include "Socket.hpp"

namespace TcpServerModule
{
    using namespace LogModule;
    using namespace SocketModule;
    using handler_t = std::function<bool(SockPtr, InetAddr)>;

    class TcpServer
    {
    public:
        TcpServer(int port)
            :_listenSockptr(std::make_unique<TcpSocket>())
            ,_port(port)
            ,_running(false)
        {

        }
        void InitServer(handler_t handler)
        {
            _handler = handler;
            _listenSockptr->BuildTcpSocketMethod(_port);
        }

        void Loop()
        {
            _running = true;
            while(true)
            {
                //1.服务器客户端进行连接
                InetAddr Client;
                auto newsockfd = _listenSockptr->Accepter(&Client);
                if (newsockfd == nullptr)
                    continue;
                // 2. IO处理
                LOG(LogLevel::DEBUG) << "get a new client, info is: " << Client.Addr();
                //2.进行IO
                pid_t id = fork();
                if(id==0)
                {
                    //子进程
                    _listenSockptr->Close();
                    if(fork())
                    exit(0);
                    //孙子进程
                    _handler(newsockfd,Client);
                    exit(0);
                }
                //父进程
                newsockfd->Close();//关闭用于信息交互的网络套接字，父进程只进行accept连接
                waitpid(id,nullptr,0);
            }


        }

        ~TcpServer()
        {
            _listenSockptr->Close();
        }

        std::unique_ptr<Socket> _listenSockptr;
        bool _running;
        handler_t _handler;
        int _port;
    };
}